using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NLog;

namespace FileSyncApp
{
    /// <summary>
    /// 多任务同步管理器
    /// 负责管理和调度多个文件同步任务，支持并发执行和优先级控制
    /// </summary>
    public class MultiTaskSyncManager
    {
        /// <summary>
        /// NLog日志记录器
        /// </summary>
        private static readonly Logger logger = LogManager.GetCurrentClassLogger();
        
        /// <summary>
        /// 任务集合，使用线程安全的字典存储
        /// </summary>
        private readonly ConcurrentDictionary<string, SyncTask> _tasks;
        
        /// <summary>
        /// 任务队列，按优先级排序
        /// </summary>
        private readonly ConcurrentQueue<string> _taskQueue;
        
        /// <summary>
        /// 正在运行的任务集合
        /// </summary>
        private readonly ConcurrentDictionary<string, CancellationTokenSource> _runningTasks;
        
        /// <summary>
        /// 最大并发任务数量
        /// </summary>
        private readonly int _maxConcurrentTasks;
        
        /// <summary>
        /// 管理器运行状态
        /// </summary>
        private bool _isRunning;
        
        /// <summary>
        /// 任务调度器取消令牌
        /// </summary>
        private CancellationTokenSource? _schedulerCancellation;
        
        /// <summary>
        /// 信号量，用于控制并发任务数量
        /// </summary>
        private readonly SemaphoreSlim _concurrencySemaphore;

        /// <summary>
        /// 任务状态变化事件
        /// </summary>
        public event Action<SyncTask>? TaskStatusChanged;
        
        /// <summary>
        /// 任务添加事件
        /// </summary>
        public event Action<SyncTask>? TaskAdded;
        
        /// <summary>
        /// 任务移除事件
        /// </summary>
        public event Action<string>? TaskRemoved;
        
        /// <summary>
        /// 日志消息事件
        /// </summary>
        public event Action<string>? LogMessage;

        /// <summary>
        /// 获取管理器运行状态
        /// </summary>
        public bool IsRunning => _isRunning;
        
        /// <summary>
        /// 获取所有任务列表
        /// </summary>
        public IReadOnlyList<SyncTask> Tasks => _tasks.Values.ToList();
        
        /// <summary>
        /// 获取正在运行的任务数量
        /// </summary>
        public int RunningTaskCount => _runningTasks.Count;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="maxConcurrentTasks">最大并发任务数量，默认为3</param>
        public MultiTaskSyncManager(int maxConcurrentTasks = 3)
        {
            _maxConcurrentTasks = Math.Max(1, maxConcurrentTasks);
            _tasks = new ConcurrentDictionary<string, SyncTask>();
            _taskQueue = new ConcurrentQueue<string>();
            _runningTasks = new ConcurrentDictionary<string, CancellationTokenSource>();
            _concurrencySemaphore = new SemaphoreSlim(_maxConcurrentTasks, _maxConcurrentTasks);
            _isRunning = false;
        }

        /// <summary>
        /// 启动多任务同步管理器
        /// </summary>
        public void Start()
        {
            if (_isRunning)
            {
                LogMessage?.Invoke("多任务同步管理器已在运行中");
                return;
            }

            _isRunning = true;
            _schedulerCancellation = new CancellationTokenSource();
            
            // 启动任务调度器
            Task.Run(() => TaskSchedulerLoop(_schedulerCancellation.Token));
            
            LogMessage?.Invoke($"多任务同步管理器已启动，最大并发数: {_maxConcurrentTasks}");
            logger.Info($"多任务同步管理器启动，最大并发数: {_maxConcurrentTasks}");
        }

        /// <summary>
        /// 停止多任务同步管理器
        /// </summary>
        public async Task StopAsync()
        {
            if (!_isRunning) return;

            _isRunning = false;
            _schedulerCancellation?.Cancel();

            // 停止所有正在运行的任务
            var stopTasks = _runningTasks.Keys.ToList();
            foreach (var taskId in stopTasks)
            {
                await StopTaskAsync(taskId);
            }

            LogMessage?.Invoke("多任务同步管理器已停止");
            logger.Info("多任务同步管理器停止");
        }

        /// <summary>
        /// 添加同步任务
        /// </summary>
        /// <param name="task">要添加的同步任务</param>
        /// <returns>是否添加成功</returns>
        public bool AddTask(SyncTask task)
        {
            if (task == null) return false;

            // 验证路径
            if (!Directory.Exists(task.SourcePath))
            {
                task.Status = SyncTaskStatus.Error;
                task.LastError = $"源文件夹不存在: {task.SourcePath}";
                LogMessage?.Invoke($"添加任务失败: {task.LastError}");
                return false;
            }

            if (_tasks.TryAdd(task.Id, task))
            {
                // 将任务加入队列
                _taskQueue.Enqueue(task.Id);
                
                TaskAdded?.Invoke(task);
                LogMessage?.Invoke($"已添加同步任务: {task.Name}");
                logger.Info($"添加同步任务: {task}");
                return true;
            }

            return false;
        }

        /// <summary>
        /// 移除同步任务
        /// </summary>
        /// <param name="taskId">任务ID</param>
        /// <returns>是否移除成功</returns>
        public async Task<bool> RemoveTaskAsync(string taskId)
        {
            if (!_tasks.TryGetValue(taskId, out var task)) return false;

            // 如果任务正在运行，先停止它
            if (task.Status == SyncTaskStatus.Running)
            {
                await StopTaskAsync(taskId);
            }

            if (_tasks.TryRemove(taskId, out _))
            {
                TaskRemoved?.Invoke(taskId);
                LogMessage?.Invoke($"已移除同步任务: {task.Name}");
                logger.Info($"移除同步任务: {task}");
                return true;
            }

            return false;
        }

        /// <summary>
        /// 启动指定任务
        /// </summary>
        /// <param name="taskId">任务ID</param>
        /// <returns>是否启动成功</returns>
        public bool StartTask(string taskId)
        {
            if (!_tasks.TryGetValue(taskId, out var task)) return false;
            
            if (task.Status == SyncTaskStatus.Running)
            {
                LogMessage?.Invoke($"任务已在运行中: {task.Name}");
                return false;
            }

            // 将任务重新加入队列
            task.Status = SyncTaskStatus.Pending;
            _taskQueue.Enqueue(taskId);
            
            LogMessage?.Invoke($"任务已加入执行队列: {task.Name}");
            return true;
        }

        /// <summary>
        /// 停止指定任务
        /// </summary>
        /// <param name="taskId">任务ID</param>
        /// <returns>异步任务</returns>
        public async Task StopTaskAsync(string taskId)
        {
            if (!_tasks.TryGetValue(taskId, out var task)) return;

            if (_runningTasks.TryRemove(taskId, out var cancellationSource))
            {
                cancellationSource.Cancel();
                task.Status = SyncTaskStatus.Stopped;
                task.CompletedAt = DateTime.Now;
                
                // 停止关联的同步服务
                task.SyncService?.StopSync();
                task.SyncService = null;
                
                // 释放信号量
                _concurrencySemaphore.Release();
                
                TaskStatusChanged?.Invoke(task);
                LogMessage?.Invoke($"任务已停止: {task.Name}");
                logger.Info($"停止任务: {task}");
            }
        }

        /// <summary>
        /// 暂停指定任务
        /// </summary>
        /// <param name="taskId">任务ID</param>
        public void PauseTask(string taskId)
        {
            if (_tasks.TryGetValue(taskId, out var task) && task.Status == SyncTaskStatus.Running)
            {
                task.Status = SyncTaskStatus.Paused;
                task.SyncService?.StopSync();
                
                TaskStatusChanged?.Invoke(task);
                LogMessage?.Invoke($"任务已暂停: {task.Name}");
            }
        }

        /// <summary>
        /// 恢复指定任务
        /// </summary>
        /// <param name="taskId">任务ID</param>
        public void ResumeTask(string taskId)
        {
            if (_tasks.TryGetValue(taskId, out var task) && task.Status == SyncTaskStatus.Paused)
            {
                task.Status = SyncTaskStatus.Pending;
                _taskQueue.Enqueue(taskId);
                
                LogMessage?.Invoke($"任务已恢复: {task.Name}");
            }
        }

        /// <summary>
        /// 获取指定任务
        /// </summary>
        /// <param name="taskId">任务ID</param>
        /// <returns>同步任务，如果不存在则返回null</returns>
        public SyncTask? GetTask(string taskId)
        {
            _tasks.TryGetValue(taskId, out var task);
            return task;
        }

        /// <summary>
        /// 任务调度器循环
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        private async Task TaskSchedulerLoop(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    // 等待可用的并发槽位
                    await _concurrencySemaphore.WaitAsync(cancellationToken);
                    
                    // 从队列中获取下一个任务
                    if (_taskQueue.TryDequeue(out var taskId) && _tasks.TryGetValue(taskId, out var task))
                    {
                        // 检查任务状态
                        if (task.Status == SyncTaskStatus.Pending)
                        {
                            // 启动任务
                            _ = Task.Run(() => ExecuteTaskAsync(task, cancellationToken), cancellationToken);
                        }
                        else
                        {
                            // 任务状态不正确，释放信号量
                            _concurrencySemaphore.Release();
                        }
                    }
                    else
                    {
                        // 队列为空，释放信号量并等待
                        _concurrencySemaphore.Release();
                        await Task.Delay(1000, cancellationToken);
                    }
                }
                catch (OperationCanceledException)
                {
                    break;
                }
                catch (Exception ex)
                {
                    logger.Error(ex, "任务调度器发生错误");
                    await Task.Delay(1000, cancellationToken);
                }
            }
        }

        /// <summary>
        /// 执行单个同步任务
        /// </summary>
        /// <param name="task">要执行的任务</param>
        /// <param name="cancellationToken">取消令牌</param>
        private async Task ExecuteTaskAsync(SyncTask task, CancellationToken cancellationToken)
        {
            var taskCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
            
            try
            {
                // 将任务添加到运行列表
                _runningTasks.TryAdd(task.Id, taskCancellation);
                
                // 更新任务状态
                task.Status = SyncTaskStatus.Running;
                task.StartedAt = DateTime.Now;
                TaskStatusChanged?.Invoke(task);
                
                LogMessage?.Invoke($"开始执行任务: {task.Name}");
                logger.Info($"开始执行任务: {task}");
                
                // 创建并配置同步服务
                var syncService = new FileSyncService();
                task.SyncService = syncService;
                
                // 订阅同步服务事件
                syncService.LogMessage += (message) => LogMessage?.Invoke($"[{task.Name}] {message}");
                syncService.FileCountChanged += (count) => 
                {
                    task.TotalFileCount = count;
                    TaskStatusChanged?.Invoke(task);
                };
                
                // 启动同步
                syncService.StartSync(task.SourcePath, task.TargetPath);
                
                // 等待取消或保持运行状态
                while (!taskCancellation.Token.IsCancellationRequested && syncService.IsRunning)
                {
                    await Task.Delay(1000, taskCancellation.Token);
                }
                
                // 任务完成
                task.Status = SyncTaskStatus.Completed;
                task.CompletedAt = DateTime.Now;
                
                LogMessage?.Invoke($"任务执行完成: {task.Name}");
                logger.Info($"任务执行完成: {task}");
            }
            catch (OperationCanceledException)
            {
                task.Status = SyncTaskStatus.Stopped;
                task.CompletedAt = DateTime.Now;
                LogMessage?.Invoke($"任务被取消: {task.Name}");
            }
            catch (Exception ex)
            {
                task.Status = SyncTaskStatus.Error;
                task.LastError = ex.Message;
                task.CompletedAt = DateTime.Now;
                
                LogMessage?.Invoke($"任务执行失败: {task.Name} - {ex.Message}");
                logger.Error(ex, $"任务执行失败: {task}");
            }
            finally
            {
                // 清理资源
                task.SyncService?.StopSync();
                task.SyncService = null;
                
                _runningTasks.TryRemove(task.Id, out _);
                TaskStatusChanged?.Invoke(task);
                
                // 释放信号量
                _concurrencySemaphore.Release();
                
                taskCancellation.Dispose();
            }
        }
    }
}